package com.woniuxy.project115.kaer.tenant.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.project115.kaer.tenant.dto.TenantStoreDto;
import com.woniuxy.project115.kaer.tenant.entity.OrderEvaluate;
import com.woniuxy.project115.kaer.tenant.entity.TenantStore;
import com.woniuxy.project115.kaer.tenant.mapper.OrderEvaluateMapper;
import com.woniuxy.project115.kaer.tenant.mapper.TenantStoreMapper;
import com.woniuxy.project115.kaer.tenant.param.UpdateStoreInfoParam;
import com.woniuxy.project115.kaer.tenant.param.UserSearchParam;
import com.woniuxy.project115.kaer.tenant.service.TenantStoreService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.project115.kaer.tenant.util.Data;
import com.woniuxy.project115.kaer.tenant.util.DistanceCalculator;
import org.apdplat.word.WordSegmenter;
import org.apdplat.word.segmentation.Word;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author HuH
 * @since 2025年02月20日
 */
@Service
public class TenantStoreServiceImpl extends ServiceImpl<TenantStoreMapper, TenantStore> implements TenantStoreService {
    @Resource
    private TenantStoreMapper tenantStoreMapper;

    @Resource
    private OrderEvaluateMapper orderEvaluateMapper;

    @Override
    public void updateScores() {
        List<TenantStore> tenantStores = tenantStoreMapper.selectAll();
        for (TenantStore tenantStore : tenantStores) {
            //根据店铺id查询该店铺近三个月内的所有评价
            LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai")).minusMonths(3);
            List<OrderEvaluate> evaluates = orderEvaluateMapper.selectList(
                    new QueryWrapper<OrderEvaluate>().eq("store_id", tenantStore.getStoreId())
                            .ge("evaluate_time", localDateTime)
                            .eq("comment_id", 0)
            );
            System.out.println(evaluates);
            double averageScore = calculatesAverageScore(evaluates);
            tenantStore.setScore(averageScore);
            tenantStoreMapper.updateById(tenantStore);
        }
    }

    @Override
    public TenantStore getStoreInfo(Integer tenantInfoId) throws Exception {
        TenantStore tenantStore = tenantStoreMapper.selectOne(
                new QueryWrapper<TenantStore>().eq("tenant_info_id", tenantInfoId)
        );
        System.out.println(tenantStore);
        if (tenantStore == null) {
            throw new Exception("店铺尚未入驻");
        }
        return tenantStore;
    }

    @Override
    public void updateStoreInfo(UpdateStoreInfoParam param, Integer tenantInfoId) throws Exception {
        TenantStore tenantStore = tenantStoreMapper.selectOne(
                new QueryWrapper<TenantStore>().eq("tenant_info_id", tenantInfoId)
        );
        if (tenantStore == null) {
            throw new Exception("店铺尚未入驻");
        }
        tenantStore.setIntroduction(param.getIntroduction())
                .setOpenTime(param.getOpenTime().toLocalTime())
                .setCloseTime(param.getCloseTime().toLocalTime())
                .setStorePhone(param.getStorePhone())
                .setStoreContacts(param.getStoreContacts());
        tenantStoreMapper.updateById(tenantStore);
    }

    @Override
    public Page<TenantStoreDto> userSearch(UserSearchParam param) throws Exception {
        Page<TenantStore> page = new Page<>(param.getPageNum(), param.getPageSize());
        QueryWrapper<TenantStore> wrapper = new QueryWrapper<>();
        List<Word> words = WordSegmenter.seg(param.getKeyword());

        if (!words.isEmpty()) {
            // 构建分词后的多条件查询
            wrapper.and(wq -> {
                for (Word word : words) {
                    String keyword = word.getText();
                    wq.or(qw -> qw
                            .like("store_name", keyword)
                            .or()
                            .like("introduction", keyword)
                            .or()
                            .like("address", keyword)
                    );
                }
            });
        }

        //根据类型查询店铺经营范围
        if (param.getTypeName() != null && !param.getTypeName().isEmpty()) {
            wrapper.like("business_scope", param.getTypeName());
        }

        // 添加排序规则，根据TenantStore中的longitude（经度）和latitude（纬度）属性来计算距离，然后根据距离排序
        Double targetLongitude = param.getLongitude();
        Double targetLatitude = param.getLatitude();

        if (targetLongitude != null && targetLatitude != null) {
            wrapper.orderByAsc("ACOS(SIN(RADIANS(" + targetLatitude + ")) * SIN(RADIANS(latitude)) + COS(RADIANS(" + targetLatitude + ")) * COS(RADIANS(latitude)) * COS(RADIANS(" + targetLongitude + ") - RADIANS(longitude))) * 6371");
        }

        Page<TenantStore> tenantStorePage = tenantStoreMapper.selectPage(page, wrapper);
        System.out.println(tenantStorePage);
        Page<TenantStoreDto> dtoPage = new Page<>(param.getPageNum(), param.getPageSize());
        // 创建一个新的ArrayList来存储TenantStoreDto对象
        List<TenantStoreDto> records = new ArrayList<>();

        for (TenantStore tenantStore : tenantStorePage.getRecords()) {
            TenantStoreDto dto = BeanUtil.toBean(tenantStore, TenantStoreDto.class);
            dto.setDistance(DistanceCalculator.calculateDistance(targetLongitude, targetLatitude, tenantStore.getLongitude(), tenantStore.getLatitude()));
            records.add(dto);
        }

        // 设置dtoPage的记录列表
        dtoPage.setRecords(records);

        return dtoPage;
    }

    @Override
    public void startAndEndBusiness(Integer storeId) throws Exception {
        TenantStore tenantStore = tenantStoreMapper.selectById(storeId);
        if (tenantStore == null) {
            throw new Exception("店铺不存在");
        }
        if (tenantStore.getIsOpen() == Data.STORE_BUSINESS_STATE_ONLINE) {
            tenantStore.setIsOpen(Data.STORE_BUSINESS_STATE_OFFLINE);
        } else {
            tenantStore.setIsOpen(Data.STORE_BUSINESS_STATE_ONLINE);
        }
        tenantStoreMapper.updateById(tenantStore);
    }

    private double calculatesAverageScore(List<OrderEvaluate> evaluates) {
        if (evaluates.isEmpty()) {
            return 0.0;
        }
        double totalScore = 0.0;
        for (OrderEvaluate evaluate : evaluates) {
            totalScore += evaluate.getScore();
        }
        return totalScore / evaluates.size();
    }
}
